package com.munichosica.myapp.jdbc;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.DataFormatException;

import javax.servlet.http.HttpServletRequest;


import org.apache.log4j.Logger;

import com.munichosica.myapp.dao.UsuarioDao;
import com.munichosica.myapp.dto.Persona;
import com.munichosica.myapp.dto.Rol;
import com.munichosica.myapp.dto.Usuario;
import com.munichosica.myapp.dto.UsuarioJF;
import com.munichosica.myapp.exceptions.PersonaDaoException;
import com.munichosica.myapp.exceptions.RolException;
import com.munichosica.myapp.exceptions.UsuarioException;
import com.munichosica.myapp.factory.PersonaDaoFactory;
import com.munichosica.myapp.factory.RolDaoFactory;
import com.munichosica.myapp.factory.UsuarioDaoFactory;
import com.munichosica.myapp.util.FileUtil;
import com.mysql.jdbc.jdbc2.optional.SuspendableXAConnection;

public class UsuarioDaoImpl implements UsuarioDao{

	private StringBuilder sql;
	private Logger logger=Logger.getLogger(UsuarioDaoImpl.class);
	
	@Override
	public List<UsuarioJF> listarUsuarios(String criterio, String Texto,
			String estado) throws UsuarioException{
		
		sql=new StringBuilder();
		sql.append("SELECT USU.USUCODIGO_I AS CODIGO," +
				"IFNULL(USU.USUUSUARIO_V,'') AS USUARIO," +
				"IFNULL(ROL.ROLNOMBRE_V,'') AS ROL," +
				"CONCAT(CONCAT(CONCAT(IFNULL(CONCAT(PER.PERNOMBRES_V,' '),''),' '),IFNULL(CONCAT(PER.PERPATERNO_V,' '),'')),IFNULL(PER.PERMATERNO_V,'')) AS NOMBRES," +
				"IFNULL(PER.PERDNI_V,'') AS DNI," +
				"IFNULL(PER.PERNACIMIENTO_F,'') AS NACIMIENTO," +
				"IFNULL(PER.PERMOVILCLA_V+'(CLA) ','')+" +
				"IFNULL(PER.PERMOVILMOV_V+'(MOV) ','')+" +
				"IFNULL(PER.PERMOVILNEX_V+'(NEX) ','') AS MOVIL," +
				"IFNULL(PER.PERTELEFFIJO_V,'') AS TELEFONO," +
				"IFNULL(PER.PERDOMICILIO_V,'') AS DOMICILIO," +
				"CASE USU.USUHABILITADO_C " +
				"WHEN '1' THEN 'A' " +
				"WHEN '2' THEN 'I' END AS ESTADO " +
				"FROM USUARIO USU " +
				"LEFT JOIN PERSONA PER ON PER.PERCODIGO_I=USU.PERCODIGO_D " +
				"LEFT JOIN ROL ROL ON ROL.ROLCODIGO_I=USU.ROLCODIGO_I " +
				"WHERE USU.USUHABILITADO_C LIKE '%"+estado.trim()+"%' ");
		if(!criterio.isEmpty()) sql.append("AND "+criterio.trim()+" LIKE '%"+Texto.trim()+"%'");
		
		List<UsuarioJF> list=null;
		PreparedStatement stmt=null;
		Connection conn=null;
		ResultSet rs=null;
		try {
			conn=ResourceManager.getConnection();
			stmt=conn.prepareStatement(sql.toString());
			boolean result=stmt.execute();
			if(result){
				list=new ArrayList<UsuarioJF>();
				rs=stmt.getResultSet();
				UsuarioJF usuario=null;
				while(rs.next()){
					usuario=new UsuarioJF();
					usuario.setUsucodigoI(rs.getInt("CODIGO"));
					usuario.setUsuusuarioV(rs.getString("USUARIO"));
					usuario.setUsuhabilitadoC(rs.getString("ESTADO"));
					usuario.setRolnombreV(rs.getString("ROL"));
					usuario.setPernombresV(rs.getString("NOMBRES"));
					usuario.setPerdniV(rs.getString("DNI"));
					usuario.setPernacimientoF(rs.getString("NACIMIENTO"));
					usuario.setPermovilV(rs.getString("MOVIL"));
					usuario.setPerteleffijoV(rs.getString("TELEFONO"));
					usuario.setPerdomicilioV(rs.getString("DOMICILIO"));
					list.add(usuario);
				}
			}
		} catch (SQLException e) {
			throw new UsuarioException(e.getMessage(),e);
		} finally{
			ResourceManager.close(rs);
			ResourceManager.close(stmt);
			ResourceManager.close(conn);
		}
		return list;
	}

	@Override
	public Usuario insertar(Usuario usuario) throws UsuarioException {
		sql=new StringBuilder();
		sql.append("INSERT INTO USUARIO " +
				"(USUUSUARIO_V,USUCLAVE_V,USUHABILITADO_C,PERCODIGO_D,ROLCODIGO_I,USUFOTO_B,USUFOTOEXT_C) " +
				"VALUES (?, ?, '1', ?, ?, ?,?)");
		Connection conn=null;
		PreparedStatement stmt=null;
		ResultSet rs=null;
		try {
			conn=ResourceManager.getConnection();
			stmt=conn.prepareStatement(sql.toString(),PreparedStatement.RETURN_GENERATED_KEYS);
			stmt.setString(1, usuario.getUsuusuarioV());
			stmt.setString(2, usuario.getPersona().getPerdniV());
			stmt.setLong(3, usuario.getPersona().getPercodigoD());
			stmt.setInt(4, usuario.getRol().getRolcodigoI());
			stmt.setBytes(5, usuario.getFoto());
			stmt.setString(6, usuario.getExtension());
			int results=stmt.executeUpdate();
			if(results>0){
				rs=stmt.getGeneratedKeys();
				if(rs.next()){
					usuario.setUsucodigoI(rs.getInt(1));
				}
			}
		} catch (SQLException e) {
			throw new UsuarioException(e.getMessage(),e);
		} finally{
			ResourceManager.close(rs);
			ResourceManager.close(stmt);
			ResourceManager.close(conn);
		}
		return usuario;
	}

	@Override
	public Usuario modificar(Usuario usuario) throws UsuarioException {
		sql=new StringBuilder();
		sql.append("UPDATE USUARIO " +
				"SET USUUSUARIO_V=?, " +
				"ROLCODIGO_I=? ");
		if(usuario.getFoto()!=null){
			sql.append(", " +
				"USUFOTO_B=?," +
				"USUFOTOEXT_C=?");
		}
		sql.append("WHERE USUCODIGO_I=?");
		Connection conn=null;
		PreparedStatement stmt=null;
		ResultSet rs=null;
		try {
			conn=ResourceManager.getConnection();
			stmt=conn.prepareStatement(sql.toString());
			stmt.setString(1, usuario.getUsuusuarioV());
			stmt.setInt(2, usuario.getRol().getRolcodigoI());
			if(usuario.getFoto()!=null){
				stmt.setBytes(3, usuario.getFoto());
				stmt.setString(4, usuario.getExtension());
				stmt.setInt(5, usuario.getUsucodigoI());
			}else{
				stmt.setInt(3, usuario.getUsucodigoI());
			}
			
			stmt.executeUpdate();
		} catch (SQLException e) {
			throw new UsuarioException(e.getMessage(),e);
		} finally{
			ResourceManager.close(rs);
			ResourceManager.close(stmt);
			ResourceManager.close(conn);
		}
		return usuario;
	}

	@Override
	public Usuario obtener(Integer codigo) throws UsuarioException {
		sql=new StringBuilder();
		sql.append("SELECT USUCODIGO_I AS CODIGO," +
				"USUUSUARIO_V AS USUARIO," +
				"USUCLAVE_V AS CLAVE," +
				"USUHABILITADO_C AS ESTADO," +
				"PERCODIGO_D AS PERSONA," +
				"ROLCODIGO_I AS ROL," +
				"USUFOTO_B AS FOTO," +
				"USUFOTOEXT_C AS EXTENSION " +
				"FROM USUARIO " +
				"WHERE USUCODIGO_I=?");
		Connection conn=null;
		PreparedStatement stmt=null;
		ResultSet rs=null;
		Usuario usuario=null;
		try {
			conn=ResourceManager.getConnection();
			stmt=conn.prepareStatement(sql.toString());
			stmt.setInt(1, codigo);
			boolean results=stmt.execute();
			if(results){
				usuario=new Usuario();
				rs=stmt.getResultSet();
				rs.next();
				usuario.setUsucodigoI(rs.getInt("CODIGO"));
				usuario.setUsuusuarioV(rs.getString("USUARIO"));
				usuario.setPass(rs.getString("CLAVE"));
				usuario.getPersona().setPercodigoD(rs.getLong("PERSONA"));
				usuario.getRol().setRolcodigoI(rs.getInt("ROL"));
				usuario.setFoto(rs.getBytes("FOTO"));
				usuario.setExtension(rs.getString("EXTENSION"));
			}
		} catch (SQLException e) {
			throw new UsuarioException(e.getMessage(),e);
		} finally{
			ResourceManager.close(rs);
			ResourceManager.close(stmt);
			ResourceManager.close(conn);
		}
		return usuario;
	}

	@Override
	public void eliminar(Integer codigo) throws UsuarioException {
		sql=new StringBuilder();
		sql.append("UPDATE USUARIO SET USUHABILITADO_C=0 WHERE USUCODIGO_I=?");
		Connection conn=null;
		PreparedStatement stmt=null;
		try {
			conn=ResourceManager.getConnection();
			stmt=conn.prepareStatement(sql.toString());
			stmt.setInt(1, codigo);
			stmt.executeUpdate();
		} catch (SQLException e) {
			throw new UsuarioException(e.getMessage(),e);
		} finally{
			ResourceManager.close(stmt);
			ResourceManager.close(conn);
		}
	}

	@Override
	public UsuarioJF procesar(UsuarioJF usuarioJF) throws UsuarioException, PersonaDaoException {
		Persona persona=new Persona();
		persona.setPercodigoD(usuarioJF.getPercodigoI());
		persona.setPerdniV(usuarioJF.getPerdniV());
		persona.setPerdomicilioV(usuarioJF.getPerdomicilioV());
		persona.setPeremailV(usuarioJF.getPeremailV());
		persona.setPerestadocivilC(usuarioJF.getPerestadocivilC());
		persona.setPermaternoV(usuarioJF.getPermaternoV());
		persona.setPermovilclaV(usuarioJF.getPermovilclaV());
		persona.setPermovilmovV(usuarioJF.getPermovilmovV());
		persona.setPermovilnexV(usuarioJF.getPermovilnexV());
		persona.setPernacimientoF(usuarioJF.getPernacimientoF());
		persona.setPernombresV(usuarioJF.getPernombresV());
		persona.setPerpaternoV(usuarioJF.getPerpaternoV());
		persona.setPersexoC(usuarioJF.getPersexoC());
		persona.setPerteleffijoV(usuarioJF.getPerteleffijoV());
		persona.setPerubdptoV(usuarioJF.getPerubdptoV());
		persona.setPerubdptonombreV(usuarioJF.getPerubdptonombreV());
		persona.setPerubprovV(usuarioJF.getPerubprovV());
		persona.setPerubprovnombreV(usuarioJF.getPerubprovnombreV());
		persona.setPerubidistV(usuarioJF.getPerubidistV());
		persona.setPerubidistnombreV(usuarioJF.getPerubidistnombreV());
		persona.setPerusuarioV(usuarioJF.getPerusuarioV());
		persona.setPeripV(usuarioJF.getPeripV());
	
		Rol rol=new Rol();
		rol.setRolcodigoI(usuarioJF.getRolcodigoI());
		
		Usuario usuario=new Usuario();
		usuario.setUsucodigoI(usuarioJF.getUsucodigoI());
		usuario.setUsuusuarioV(usuarioJF.getUsuusuarioV());
		usuario.setRol(rol);
		usuario.setPersona(persona);
		usuario.setFoto(usuarioJF.getUsufotoB());
		usuario.setExtension(usuarioJF.getUsufotoExtV());
		
		if(persona.getPercodigoD()==null||persona.getPercodigoD()==0){
			if(PersonaDaoFactory.create().existeDniPersona(persona.getPerdniV())){
				persona=PersonaDaoFactory.create().obtenerPorDni(persona.getPerdniV());
			}else{
				PersonaDaoFactory.create().insertar(persona);
				usuarioJF.setPercodigoI(persona.getPercodigoD());
				logger.info("PersonaDaoFactory.create().insertar(persona); codigo: "+persona.getPercodigoD());
			}
		}else{
			PersonaDaoFactory.create().modificar(persona);
		}
		
		if(usuario.getUsucodigoI()==null||usuario.getUsucodigoI()==0){
			usuario.setPersona(persona);
			UsuarioDaoFactory.create().insertar(usuario);
			usuarioJF.setUsucodigoI(usuario.getUsucodigoI());
			logger.info("UsuarioDaoFactory.create().insertar(usuario); codigo: "+usuario.getUsucodigoI());
		}else{
			UsuarioDaoFactory.create().modificar(usuario);
		}
		return usuarioJF;
	}

	@Override
	public UsuarioJF obtenerUsuario(HttpServletRequest request,Integer codigo) throws UsuarioException, PersonaDaoException, RolException, UnsupportedEncodingException, IOException, DataFormatException {
		Usuario usuario=UsuarioDaoFactory.create().obtener(codigo);
		Persona persona=PersonaDaoFactory.create().obtener(usuario.getPersona().getPercodigoD());
		Rol rol=RolDaoFactory.create().obtener(usuario.getRol().getRolcodigoI());
		UsuarioJF usuarioJF=new UsuarioJF();
		usuarioJF.setUsuusuarioV(usuario.getUsuusuarioV());
		usuarioJF.setUsucodigoI(usuario.getUsucodigoI());
		usuarioJF.setPercodigoI(persona.getPercodigoD());
		usuarioJF.setPerdniV(persona.getPerdniV());
		usuarioJF.setPerdomicilioV(persona.getPerdomicilioV());
		usuarioJF.setPeremailV(persona.getPeremailV());
		usuarioJF.setPerestadocivilC(persona.getPerestadocivilC());
		usuarioJF.setPermaternoV(persona.getPermaternoV());
		usuarioJF.setPermovilclaV(persona.getPermovilclaV());
		usuarioJF.setPermovilmovV(persona.getPermovilmovV());
		usuarioJF.setPermovilnexV(persona.getPermovilnexV());
		usuarioJF.setPernacimientoF(persona.getPernacimientoF());
		usuarioJF.setPernombresV(persona.getPernombresV());
		usuarioJF.setPerpaternoV(persona.getPerpaternoV());
		usuarioJF.setPersexoC(persona.getPersexoC());
		usuarioJF.setPerteleffijoV(persona.getPerteleffijoV());
		usuarioJF.setPerubdptonombreV(persona.getPerubdptonombreV());
		usuarioJF.setPerubdptoV(persona.getPerubdptoV());
		usuarioJF.setPerubidistnombreV(persona.getPerubidistnombreV());
		usuarioJF.setPerubidistV(persona.getPerubidistV());
		usuarioJF.setPerubprovnombreV(persona.getPerubprovnombreV());
		usuarioJF.setPerubprovV(persona.getPerubprovV());
		usuarioJF.setRolcodigoI(rol.getRolcodigoI());
		usuarioJF.setRolnombreV(rol.getRolnombreV());
		if(usuario.getFoto()!=null){
			String nombreArchivo=
					FileUtil.createTempFile(request, usuario.getUsuusuarioV()+usuario.getExtension() , FileUtil.deCompress(usuario.getFoto()) );
			usuarioJF.setUsuArchivoV(nombreArchivo);
		}

		return usuarioJF;
	}

	@Override
	public boolean existeUsuario(String usuario) throws UsuarioException {
		sql=new StringBuilder();
		sql.append("SELECT COUNT(*) CANTIDAD FROM USUARIO WHERE USUUSUARIO_V=?");
		Connection conn=null;
		PreparedStatement stmt=null;
		ResultSet rs=null;
		try {
			conn=ResourceManager.getConnection();
			stmt=conn.prepareStatement(sql.toString());
			stmt.setString(1, usuario);
			boolean results=stmt.execute();
			if(results){
				rs=stmt.getResultSet();
				if(rs.next()){
					int count=rs.getInt("CANTIDAD");
					if(count>0){
						return true;
					}
				}
			}
			
		} catch (SQLException e) {
			throw new UsuarioException(e.getMessage(),e);
		} finally{
			ResourceManager.close(rs);
			ResourceManager.close(stmt);
			ResourceManager.close(conn);
		}
		
		return false;
	}

	@Override
	public List<Usuario> listarTodos() throws UsuarioException {
		sql=new StringBuilder();
		sql.append("SELECT USU.USUCODIGO_I AS CODIGO, " +
				"USU.USUUSUARIO_V AS USUARIO, " +
				"CONCAT(PER.PERNOMBRES_V,CONCAT(' ',CONCAT(PER.PERPATERNO_V,CONCAT(' ',PER.PERMATERNO_V)))) AS NOMBRES " +
				"FROM USUARIO USU " +
				"INNER JOIN PERSONA PER ON PER.PERCODIGO_I=USU.PERCODIGO_D " +
				"WHERE USU.USUHABILITADO_C='1'");
		List<Usuario> list=null;
		PreparedStatement stmt=null;
		Connection conn=null;
		ResultSet rs=null;
		try {
			conn=ResourceManager.getConnection();
			stmt=conn.prepareStatement(sql.toString());
			boolean result=stmt.execute();
			if(result){
				list=new ArrayList<Usuario>();
				rs=stmt.getResultSet();
				Usuario usuario=null;
				while(rs.next()){
					usuario=new Usuario();
					usuario.setUsucodigoI(rs.getInt("CODIGO"));
					usuario.setUsuusuarioV(rs.getString("USUARIO"));
					usuario.getPersona().setPernombresV(rs.getString("NOMBRES"));
					list.add(usuario);
				}
			}
		} catch (SQLException e) {
			throw new UsuarioException(e.getMessage(),e);
		} finally{
			ResourceManager.close(rs);
			ResourceManager.close(stmt);
			ResourceManager.close(conn);
		}
		return list;
	}

	@Override
	public Usuario obtener(String Usuario) throws UsuarioException {
		System.out.println("USUARIO: "+Usuario);
		sql=new StringBuilder();
		sql.append("SELECT USUCODIGO_I AS CODIGO," +
				"USUUSUARIO_V AS USUARIO," +
				"USUCLAVE_V AS CLAVE," +
				"USUHABILITADO_C AS ESTADO," +
				"PERCODIGO_D AS PERSONA," +
				"ROLCODIGO_I AS ROL," +
				"USUTIPO_C AS TIPO," +
				"USUTIPOCODIGO_I AS TIPO_CODIGO " +
				"FROM USUARIO " +
				"WHERE USUUSUARIO_V=?");
		Connection conn=null;
		PreparedStatement stmt=null;
		ResultSet rs=null;
		Usuario usuario=null;
		try {
			conn=ResourceManager.getConnection();
			stmt=conn.prepareStatement(sql.toString());
			stmt.setString(1, Usuario);
			boolean results=stmt.execute();
			if(results){
				usuario=new Usuario();
				rs=stmt.getResultSet();
				rs.next();
				usuario.setUsucodigoI(rs.getInt("CODIGO"));
				usuario.setUsuusuarioV(rs.getString("USUARIO"));
				usuario.setPass(rs.getString("CLAVE"));
				usuario.getPersona().setPercodigoD(rs.getLong("PERSONA"));
				usuario.getRol().setRolcodigoI(rs.getInt("ROL"));
				usuario.setTipo(rs.getString("TIPO"));
				usuario.setTipoCodigo(rs.getString("TIPO_CODIGO"));
			}
		} catch (SQLException e) {
			throw new UsuarioException(e.getMessage(),e);
		} finally{
			ResourceManager.close(rs);
			ResourceManager.close(stmt);
			ResourceManager.close(conn);
		}
		return usuario;
	}
	
}
